package com.aivin.maproutelib.manager;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;

import com.aivin.maproutelib.config.WkConfig;
import com.aivin.maproutelib.area.AreaMassif;
import com.aivin.maproutelib.line.GaoDeLine;
import com.aivin.maproutelib.bean.GaoDeMarker;
import com.aivin.maproutelib.bean.WkGDmap;
import com.aivin.maproutelib.tool.BitmapWrap;
import com.aivin.maproutelib.bean.WaypointInfo;
import com.aivin.maproutelib.param.MyMarkerOption;
import com.aivin.maproutelib.tool.BitmapTool;
import com.aivin.maproutelib.area.AreaObstacle;
import com.aivin.maproutelib.param.OLineOption;
import com.aivin.maproutelib.line.HelperLine;
import com.aivin.maproutelib.tool.MapTool;
import com.aivin.wkmaplib.R;
import com.aivin.maproutelib.tool.WkToastTools;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;

import java.util.ArrayList;
import java.util.List;

/**
 * 航线规划 管理类
 */
public class MapRouteManager {
    /**
     * 边界线颜色
     */
    private final int COLOR_BOUNDARY_LINE = Color.parseColor("#0087E2");

    /**用户添加的，边界点，LatLng */
    private List<LatLng> boundaryLatLngList = new ArrayList<>();
    /**边界线的，第一个和最后一个点的坐标点*/
    private List<LatLng> boundAreaFirstEndLatlngList = new ArrayList<>();
    /**用户添加的，边界点，Marker */
    private List<GaoDeMarker> boundMarkerList = new ArrayList<>();
    /**边界线 [1,n]*/
    private GaoDeLine boundLine;
    /**边界线 [n ,0]*/
    private GaoDeLine boundLineEnd;
    /** 障碍物坐标点 */
    private List<List<LatLng> > obstacleLists = new ArrayList<>();
    /**边界点间的距离 mark */
    private List<GaoDeMarker> distanceMakerList = new ArrayList<>();
    /**当前选中的marker的索引*/
    private int selectMarkerIndex;
    /**喷福，航线间距 */
    private double widthLen = 20.0d;
    /** 航线生成角度 */
    private float mDirection;
    /**规划后生成的航点集合*/
    private List<LatLng> lastLatLngList = new ArrayList<>();
    /**飞行航点的marker*/
    private List<Marker> flyPointsMakers = new ArrayList<>();
    @SuppressLint("StaticFieldLeak")
    private static MapRouteManager instance;
    private WkGDmap mMap;
    private Context mContext;
    private BitmapWrap bitmapWrap = new BitmapWrap();
    /**规划后的航线*/
    private GaoDeLine mFlyPointsLine;

    /**障碍物的边*/
    private List<GaoDeLine> mObstacleLines = new ArrayList<>();

    public static MapRouteManager getInstance() {
        if (instance == null) {
            synchronized (MapRouteManager.class) {
                if (instance == null) {
                    instance = new MapRouteManager();
                }
            }
        }
        return instance;
    }


    public void initMap(Context context, WkGDmap map) {
        mContext = context;
        mMap = map;
    }

    public void updateSelectMakerIcon() {
        if (boundMarkerList != null && boundMarkerList.size() > 0) {
            // 更新索引和maker图标
            updateSelectMarkerIndexAndIcon(boundMarkerList.get(selectMarkerIndex));
            // 自动对齐边
            autoLine(false);
        }
    }


    /**更新当前 被点击的marker 的索引标记 和 maker图标*/
    public void updateSelectMarkerIndexAndIcon(GaoDeMarker iMarker) {
        for (int i = 0; i < boundMarkerList.size(); i++) {
            if (boundMarkerList.get(i).equals(iMarker)) {
                if (boundMarkerList.get(selectMarkerIndex) != null) {
                    // 将上一个选中的点改成 未选中UI状态  btn_dingdian_ico_0
                    boundMarkerList.get(selectMarkerIndex).setIcon(BitmapTool.readBitmapById(mContext, R.mipmap.btn_dingdian_ico_0_new));
                    boundMarkerList.get(selectMarkerIndex).setRotate(0);
                    mDirection = 0;
                }
                // icon_direction
                boundMarkerList.get(i).setIcon(BitmapTool.rotateBitmap(mContext, R.mipmap.icon_direction_new, mDirection));
                selectMarkerIndex = i;
            }
        }
    }

    /**
     * maker 点回退
     */
    public void markerGoback() {
        if(boundMarkerList ==null || boundMarkerList.size()<1){
            WkToastTools.toastInfo(mContext,mContext.getString(R.string.cannotgoback));
            return;
        }
        // 移除最后一个maker
        int lastMakerIndex = boundMarkerList.size()-1;
        GaoDeMarker lastMaker = boundMarkerList.get(lastMakerIndex) ;
        boundMarkerList.remove(lastMaker) ;// 从列表中移除
        lastMaker.remove(); // 从地图中移除
        //移除最后一个边界点坐标
        boundaryLatLngList.remove(boundaryLatLngList.size()-1);
        // 清除航线
        if (mFlyPointsLine != null) {
            mFlyPointsLine.remove();
            mFlyPointsLine = null;
        }
        // 将剩余的点重新绘制线条
        addBoundaryMarker(null , false) ;
    }


    private void clearFlyPointsMaker(){
        if(flyPointsMakers !=null){
            for(Marker marker :flyPointsMakers){
                marker.remove();
            }
            flyPointsMakers.clear();
        }
    }


    private void clearAllObstacleLines(){
        for(GaoDeLine line :mObstacleLines){
            line.remove();
        }
        mObstacleLines.clear();
    }
    public void clearAll() {
        clearAllObstacleLines();


        if(boundaryLatLngList !=null){
            boundaryLatLngList.clear();
        }

        if(boundMarkerList !=null){
            for (GaoDeMarker marker : boundMarkerList) {
                marker.remove();
            }
            boundMarkerList.clear();
        }

        if(distanceMakerList !=null){
            for(int i = 0; i< distanceMakerList.size(); i++){
                GaoDeMarker marker = distanceMakerList.get(i);
                marker.remove();
            }
            distanceMakerList.clear();
        }

        clearFlyPointsMaker();//clearAll

        if(obstacleLists!=null){
            obstacleLists.clear();
        }

        if (boundLine != null) {
            boundLine.remove();
            boundLine = null;
        }

        if (boundLineEnd != null) {
            boundLineEnd.remove();
            boundLineEnd = null;
        }

        mDirection = 0;
        if (mFlyPointsLine != null) {
            mFlyPointsLine.remove();
            mFlyPointsLine = null;
        }
    }


    /**
     * 更新整个地块边界线
     */
    private void updateBundLines(){
        if (boundLine != null) {
            boundLine.remove();
            boundLine = null;
        }

        if (boundLineEnd != null) {
            boundLineEnd.remove();
            boundLineEnd = null;
        }

        if(boundaryLatLngList.size()>=2){

            boundAreaFirstEndLatlngList.clear();
            boundAreaFirstEndLatlngList.add(boundaryLatLngList.get(0));
            boundAreaFirstEndLatlngList.add(boundaryLatLngList.get(boundaryLatLngList.size() - 1));

            if(boundLine == null){
                boundLine = mMap.addLine( new OLineOption(boundaryLatLngList).strokeColor(COLOR_BOUNDARY_LINE).strokeWidth(WkConfig.BoundLineWidth) , WkConfig.Z_INDEX_90);
            }else{
                boundLine.setPosition(boundaryLatLngList);
            }

            if(boundLineEnd ==null){
                boundLineEnd = mMap.addLine(new OLineOption(boundAreaFirstEndLatlngList).strokeColor(COLOR_BOUNDARY_LINE).strokeWidth(WkConfig.BoundLineWidth) ,WkConfig.Z_INDEX_90);
            }else{
                boundLineEnd.setPosition(boundAreaFirstEndLatlngList);
            }
        }

    }

    /**
     * 添加边界点和边界连线
     * @param isAddMaker  点击地图添加新加maker ， false 就是回退，重新绘制点而已
     */
    public void addBoundaryMarker(LatLng latLng ,  boolean isAddMaker) {
        if(isAddMaker){
            boundaryLatLngList.add(latLng);
            // btn_dingdian_ico_0
            boundMarkerList.add(mMap.addMarker(new MyMarkerOption(latLng).icon(R.mipmap.btn_dingdian_ico_0_new).center().setDraggable(true)));
        }

        updateBundLines(); // addBoundaryMarker
        updateDistanceMarkers();// 坐标点数增加或减少时
        for (int i = 0; i < boundMarkerList.size(); i++) {
            boundMarkerList.get(i).setSnippet(String.valueOf(i));
        }
    }



    public void onMarkerDragStart(GaoDeMarker marker) {
        int snippet = Integer.parseInt(marker.getSnippet());
        boundMarkerList.set(snippet, marker);
        boundaryLatLngList.set(snippet, marker.getPosition());
    }

    public void onMarkerDrag(GaoDeMarker marker) {
        int snippet = Integer.parseInt(marker.getSnippet());
        boundMarkerList.set(snippet, marker);
        boundaryLatLngList.set(snippet, marker.getPosition());

        updateDistanceMarkers(); // onMarkerDrag
        updateBundLines(); // onMarkerDrag
    }

    public void onMarkerDragEnd(GaoDeMarker marker) {
        int snippet = Integer.parseInt(marker.getSnippet());
        boundMarkerList.set(snippet, marker);
        boundaryLatLngList.set(snippet, marker.getPosition()); // 更新拖动后的marker坐标信息

        createLine(); //onMarkerDragEnd
    }


    /**
     * 更新距离标签
     */
    private void updateDistanceMarkers() {
        // 移除所有marker
        for (int i = 0; i < distanceMakerList.size(); i++) {
            GaoDeMarker marker = distanceMakerList.get(i);
            marker.remove();
        }
        distanceMakerList.clear();

        if (boundaryLatLngList.size() >= 2) {
            // 第一部分距离标签
            for (int i = 0; i <= boundaryLatLngList.size() - 2; i++) {
                LatLng pointStart = boundaryLatLngList.get(i);
                LatLng pointEnd = boundaryLatLngList.get(i + 1);
                drawDistanceMaker(pointStart, pointEnd); //
            }
            // 第二部分距离标签
            drawDistanceMaker(boundaryLatLngList.get(0), boundaryLatLngList.get(boundaryLatLngList.size() - 1));
        }
    }

    /**
     *  绘制用来显示两点之间距离的 maker
     */
    private void drawDistanceMaker(LatLng pointStart ,LatLng pointEnd  ){
        LatLng centerLL = MapTool.createLatlng((pointStart.latitude + pointEnd.latitude) / 2, (pointStart.longitude + pointEnd.longitude) / 2);
        String distance = MapTool.getDistanceStr( pointStart, pointEnd);
        GaoDeMarker marker =mMap.addMarker( new MyMarkerOption(centerLL).icon( bitmapWrap.getBitmap( mContext, R.mipmap.map_side, distance)) .center())  ;
        distanceMakerList.add(marker);
    }



    /**
     * 增加角度
     */
    public void addDirectionAngle() {
        if (boundMarkerList.size() > selectMarkerIndex && boundMarkerList.get(selectMarkerIndex) != null) {
            mDirection += 10;
            //测试旋转角度
            if (mDirection > 360) {
                mDirection -= 360;
            }
            boundMarkerList.get(selectMarkerIndex).setRotate(mDirection);
        }
    }

    /**
     * 减少角度
     */
    public void subDirectionAngle() {
        if (boundMarkerList.size() > selectMarkerIndex && boundMarkerList.get(selectMarkerIndex) != null) {
            mDirection -= 5;
            //测试旋转角度
            if (mDirection < 0) {
                mDirection += 360;
            }
            boundMarkerList.get(selectMarkerIndex).setRotate(mDirection);
        }
    }

    /**
     * 两条边切换对齐.
     * 命名A、B两条边。
     */
    private boolean isAlignA;

    /**
     * 对齐边的角度，两条边任意切换
     */
    public void autoLine(boolean isByUser) {
        if(isByUser && boundMarkerList.size()<=2 ){
            WkToastTools.toastInfo(mContext, mContext.getResources().getString(R.string.lo_please_create_line));
            return;
        }

        int index = selectMarkerIndex;
        WaypointInfo startPoint = new WaypointInfo(boundMarkerList.get(index).getPosition());
        WaypointInfo endPoint ,endPoint2 ;

        if (0 == index) {  // 首点
            endPoint = new WaypointInfo(boundMarkerList.get(1).getPosition());
            endPoint2 = new WaypointInfo(boundMarkerList.get(boundMarkerList.size() - 1).getPosition());
        }

        else if (index == (boundMarkerList.size() - 1)) {// 尾点
            endPoint = new WaypointInfo(boundMarkerList.get(0).getPosition());
            endPoint2=  new WaypointInfo(boundMarkerList.get(boundMarkerList.size() - 2).getPosition());
        }

        else  {// 中间点
            endPoint = new WaypointInfo(boundMarkerList.get(index - 1).getPosition());
            endPoint2= new WaypointInfo(boundMarkerList.get(index + 1).getPosition());
        }

        startPoint.addAlinePassedThePoint(new HelperLine(startPoint, endPoint));
        startPoint.addAlinePassedThePoint(new HelperLine(startPoint, endPoint2));

        isAlignA = !isAlignA;
        List<HelperLine> passMeLines = startPoint.getpassedMeLines();
        HelperLine selectLine = passMeLines.get(isAlignA ? 0 : 1);
        mDirection = selectLine.getRotate(startPoint);
        boundMarkerList.get(selectMarkerIndex).setRotate(mDirection);
    }


    /**
     * 生成航线
     */
    public void createLine() {
        if (boundMarkerList.size() < 3) {
            WkToastTools.toastInfo(mContext ,mContext.getString(R.string.leastPoints));
            return;
        }

        AreaMassif massif = new AreaMassif( getFunctionPointArray());
        List<WaypointInfo[] > datas= getObstaclePoint();
        for( WaypointInfo[]  data : datas){
            AreaObstacle obstacle = new AreaObstacle(data);
            massif.addObstacl(obstacle);  // 地块添加障碍物
        }

        CalculationManager calculationManager = new CalculationManager(massif);
        WaypointInfo startPoint = new WaypointInfo(boundaryLatLngList.get(selectMarkerIndex));

        List<WaypointInfo> waypointInfos = calculationManager.getAllFlyPoints(startPoint, mDirection, widthLen);
        drawFlyPointsLine(waypointInfos);// 生成的航线绘制
        drawFlyPointMakers(waypointInfos);// 绘制航点 maker
        drawObstacleLines(); // 绘制障碍物连线
    }


    /**
     * 整个地块的边界点 (用户手动点击的那些点组成的圈)
     */
    private WaypointInfo[] getFunctionPointArray() {
        WaypointInfo[] pointList =new WaypointInfo[boundaryLatLngList.size()];
        for (int i = 0; i < boundaryLatLngList.size(); i++) {
            LatLng latLng = boundaryLatLngList.get(i);
            WaypointInfo point = new WaypointInfo(latLng.latitude, latLng.longitude );
            pointList[i]=point;
        }
        return pointList;
    }



    /**
     * 整个地块里边的障碍物点
     */
    private List<WaypointInfo[] > getObstaclePoint() {
        List<WaypointInfo[]> datas = new ArrayList<>();
        for(List<LatLng> obstacleList :obstacleLists ){
            WaypointInfo[] points = new WaypointInfo[obstacleList.size()];
            for (int i = 0; i < obstacleList.size(); i++) {
                LatLng latLng = obstacleList.get(i);
                WaypointInfo point = new WaypointInfo(latLng.latitude, latLng.longitude );
                points[i] = point;
            }
            datas.add(points) ;
        }

        return datas;
    }

    public void setSprayBlessings(double spray) {
        this.widthLen = spray;
    }


    /**
     * 添加障碍物坐标点
     */
     public void addObstacle2List(List<List<LatLng>> obstacleLists  ) {
         this.obstacleLists= obstacleLists ;
    }

    /**
     * 绘制所有的 障碍物
     */
    private void drawObstacleLines() {
        if(obstacleLists==null || obstacleLists.size()==0){
            WkToastTools.toastInfo(mContext ,"没有障碍物点,无需绘制");
            return;
        }

        clearAllObstacleLines() ; //
        for(List<LatLng> obstacleList : obstacleLists){
            drawObstacleLine(obstacleList);
        }
    }


    /**
     * 绘制 一个障碍物区域
     */
    private void drawObstacleLine(List<LatLng> obstacleList ) {
        List<LatLng> mObstacleLatlngList = new ArrayList<>();
        mObstacleLatlngList.add(obstacleList.get(0));
        mObstacleLatlngList.add(obstacleList.get(obstacleList.size() - 1));


        GaoDeLine line1 =  mMap.addLine(new OLineOption(obstacleList).strokeColor(WkConfig.ObstacleLineColor).strokeWidth(WkConfig.ObstacleLineWidth));
        GaoDeLine line2 = mMap.addLine(new OLineOption(mObstacleLatlngList).strokeColor(WkConfig.ObstacleLineColor).strokeWidth(WkConfig.ObstacleLineWidth));

        mObstacleLines.add(line1);
        mObstacleLines.add(line2);
    }

    /**
     * 绘制航线到地图上
     */
    private void drawFlyPointsLine(List<WaypointInfo> pointList) {
        if (pointList.size() < 2) {
            return;
        }
        lastLatLngList.clear();

        for(int i=0 ; i<pointList.size();i++){
            LatLng latLng = pointList.get(i).getLatLng( ) ;
            lastLatLngList.add(latLng);
        }

        if (mFlyPointsLine == null) {
            OLineOption lineOption = new OLineOption(lastLatLngList);
            lineOption.strokeColor(  Color.parseColor("#FFB000") ).strokeWidth(WkConfig.BoundLineWidth);
            mFlyPointsLine = mMap.addLine(lineOption);
        } else {
            mFlyPointsLine.setPosition(lastLatLngList);
        }
    }


    /**
     * 绘制航点的maker
     */
    private void drawFlyPointMakers(List<WaypointInfo> pointList) {
        if (pointList.size() < 2) {
            return;
        }

        clearFlyPointsMaker();

        for(int i=0 ; i<pointList.size();i++){
            // 给每个航点绘制一个编号
            LatLng latLng = pointList.get(i).getLatLng( ) ;
            String str = String.valueOf(i);
            flyPointsMakers.add(mMap.addAmarker (bitmapWrap.getBitmapWidthStr(str) ,latLng));
        }
    }


    /**
     * 最后所有航点经纬度
     */
    public List<LatLng> getAllPointList() {
        return lastLatLngList;
    }

}
